package tr.edu.ege.kipler.satisfiability.completion.rules.dl;

import java.util.Iterator;

import tr.edu.ege.kipler.satisfiability.UnsatisfiableException;
import tr.edu.ege.kipler.satisfiability.blocking.BlockingStrategy;
import tr.edu.ege.kipler.satisfiability.container.ABox;
import tr.edu.ege.kipler.satisfiability.container.ConceptCategory;
import tr.edu.ege.kipler.satisfiability.container.WcsData;
import tr.edu.ege.kipler.syntax.atomicformula.ConceptAssertion;
import tr.edu.ege.kipler.syntax.concept.BinaryConcept;
import tr.edu.ege.kipler.syntax.concept.Concept;
import tr.edu.ege.kipler.syntax.concept.BinaryConcept.Constructor;

/**
 * 
 * @author İnanç Seylan
 *
 */
public class IntersectionRule extends ABoxRule {
	private ABox aBox;

	private boolean applied;

	private BlockingStrategy blocking;

	public IntersectionRule(BlockingStrategy blocking) {
		setBlocking(blocking);
	}

	public BlockingStrategy getBlocking() {
		return blocking;
	}

	public void setBlocking(BlockingStrategy blocking) {
		this.blocking = blocking;
	}

	public void apply() throws UnsatisfiableException {
		applied = false;
		aBox = getWorld().getABox();
		if (!getBlocking().isIndirectlyBlocked(aBox, getIndividual().getName())) {
			for (Iterator<Concept> i = getIndividual().conceptIterator(
					ConceptCategory.INTERSECTION); i.hasNext();) {
				Concept concept = i.next();
				decomposeIntersection(concept);
			}
		}
	}

	private void decomposeIntersection(Concept concept)
			throws UnsatisfiableException {
		if (concept instanceof BinaryConcept) {
			BinaryConcept bd = (BinaryConcept) concept;
			ConceptAssertion lhsAssert = new ConceptAssertion(bd.getLhs(),
					getIndividual().getName());
			ConceptAssertion rhsAssert = new ConceptAssertion(bd.getRhs(),
					getIndividual().getName());
			if (bd.getConstructor() == Constructor.INTERSECTION) {
				WcsData wcsData = getWcs().getData();
				if (!aBox.contains(lhsAssert)) {
					applied = true;
					wcsData.getLogger()
							.info(
									"WCS " + getWcs().getId()
											+ " Intersection rule: Adding "
											+ lhsAssert);
					wcsData.getDependencyManager().move(
							lhsAssert,
							new ConceptAssertion(concept, getIndividual()
									.getName()));
					aBox.add(lhsAssert);
					decomposeIntersection(lhsAssert.getConcept());
				}
				if (!aBox.contains(rhsAssert)) {
					applied = true;
					wcsData.getLogger()
							.info(
									"WCS " + getWcs().getId()
											+ " Intersection rule: Adding "
											+ rhsAssert);
					wcsData.getDependencyManager().move(
							rhsAssert,
							new ConceptAssertion(concept, getIndividual()
									.getName()));
					aBox.add(rhsAssert);
					decomposeIntersection(rhsAssert.getConcept());
				}
			}
		}
	}

	@Override
	public boolean isApplied() {
		return applied;
	}

}
